package Game.Objects;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

import Game.GameHelper;
import Game.Level;

/** Object creator class
 * @author Aikidos
 */
public class ObjectCreator {
	/** List of object creator entity */
	private List<ObjectCreatorEntity> _lstObjects = new ArrayList<ObjectCreatorEntity>();
	
	/** Object manager */
	private ObjectManager _objectManager;
	
	public ObjectCreator(ObjectManager objectManager) {
		_objectManager = objectManager;
	}
	
	/** Initialize object creator */
	public void init() {
		// Skeleton
		ObjectCreatorEntity entitySkeleton = new ObjectCreatorEntity();
		entitySkeleton.ClassName = "Game.Objects.Creatures.GOCSkeleton";
		entitySkeleton.Floor = 3;
		entitySkeleton.IsCreature = true;
		
		// Slime
		ObjectCreatorEntity entitySlime = new ObjectCreatorEntity();
		entitySlime.ClassName = "Game.Objects.Creatures.GOCSlime";
		entitySlime.Floor = 0;
		entitySlime.Max = 4;
		entitySlime.IsCreature = true;
		
		// Rat
		ObjectCreatorEntity entityRat = new ObjectCreatorEntity();
		entityRat.ClassName = "Game.Objects.Creatures.GOCRat";
		entityRat.Floor = 0;
		entityRat.IsCreature = true;
		
		// Bat
		ObjectCreatorEntity entityBat = new ObjectCreatorEntity();
		entityBat.ClassName = "Game.Objects.Creatures.GOCBat";
		entityBat.Max = 3;
		entityBat.Floor = 3;
		entityBat.IsCreature = true;
		
		// Troll
		ObjectCreatorEntity entityTroll = new ObjectCreatorEntity();
		entityTroll.ClassName = "Game.Objects.Creatures.GOCTroll";
		entityTroll.Floor = 1;
		entityTroll.IsCreature = true;
		
		// Zombie
		ObjectCreatorEntity entityZombie = new ObjectCreatorEntity();
		entityZombie.ClassName = "Game.Objects.Creatures.GOCZombie";
		entityZombie.Floor = 5;
		entityZombie.IsCreature = true;
		
		// Civilian
		ObjectCreatorEntity entityCivilian = new ObjectCreatorEntity();
		entityCivilian.ClassName = "Game.Objects.Creatures.GOCCivilian";
		entityCivilian.Floor = 0;
		entityCivilian.IsCreature = true;
		entityCivilian.IsUndergroundTown = true;
		
		_lstObjects.add(entitySkeleton);
		_lstObjects.add(entitySlime);
		_lstObjects.add(entityRat);
		_lstObjects.add(entityBat);
		_lstObjects.add(entityTroll);
		_lstObjects.add(entityZombie);
		_lstObjects.add(entityCivilian);
	}
	
	/** Returns object manager
	 * @return Object manager
	 */
	public ObjectManager getObjectManager() {
		return _objectManager;
	}
	
	/** Returns max spawn by class name
	 * @param className - Class name
	 * @return Max spawn
	 */
	public int getMaxSpawn(String className) {
		for (ObjectCreatorEntity entity : _lstObjects) {
			if (entity.ClassName == className) return entity.Max;
		}
		
		return 0;
	}
	
	/** Create creature
	 * @param floor - Floor
	 * @param isCreature - Object is creature?
	 * @param isUndergroundTown - Object is spawn on underground?
	 * @return
	 */
	public GameObject createCreature(int floor, boolean isCreature, boolean isUndergroundTown) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException {
		// Create available created objects class names by floor
		List<String> lstClassNames = new ArrayList<String>();
		for (ObjectCreatorEntity entity : _lstObjects)
			if ((entity.Floor <= floor) && (entity.IsCreature == isCreature) && (entity.IsUndergroundTown == isUndergroundTown))
				lstClassNames.add(entity.ClassName);
		
		if (lstClassNames.size() == 0) return null;
		else {
			// Get random class name
			String className;
			while (true) {
				className = lstClassNames.get(GameHelper.getRandom().nextInt(lstClassNames.size()));
				
				int maxSpawn = getMaxSpawn(className);
				if ((maxSpawn == 0) 
						|| (_objectManager.getObjectsByClass(className).length < maxSpawn))
					break;
				}
			
			// Create instance
			return (GameObject) Class.forName(className)
					.getConstructor(ObjectManager.class)
					.newInstance(_objectManager);
		}
	}
}
